package com.augurit.common.common.http.kt.model


/**
 *  author : yanghaozhang
 *  date : 2022/5/3 17:13
 *  description :
 */
sealed class Result<out V : Any?, out E : Exception> {

    class Success<out V : Any?>(val value: V) : Result<V, Nothing>() {

        override fun toString() = "[Success: $value]"

        override fun hashCode(): Int = value.hashCode()

        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            return other is Success<*> && value == other.value
        }
    }

    class Failure<out E : Exception>(val error: E) : Result<Nothing, E>() {

        override fun toString() = "[Failure: $error]"

        override fun hashCode(): Int = error.hashCode()

        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            return other is Failure<*> && error == other.error
        }
    }

    inline fun <X> fold(success: (V) -> X, failure: (E) -> X): X = when (this) {
        is Success -> success(this.value)
        is Failure -> failure(this.error)
    }

    companion object {
        // Factory methods
        fun <E : Exception> error(ex: E) = Failure(ex)

        fun <V : Any?> success(v: V) = Success(v)

        // 如果为空,返回错误
        fun <V : Any?> of(value: V?, fail: (() -> Exception) = { Exception() }): Result<V, Exception> =
            value?.let { success(it) } ?: error(fail())

        // 执行逻辑,如果过程中出错,返回错误
        fun <V : Any?, E : Exception> of(f: () -> V): Result<V, E> = try {
            success(f())
        } catch (ex: Exception) {
            error(ex as E)
        }
    }
}